﻿using System;
using System.Collections.Generic;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using System.Text;
using MBWebService.Core;
using MBWebService.Core.Classes;
using MBWebService.Core.Enums;
using MBWebService.Core.Interfaces;
using Microsoft.Ajax.Samples;
using System.ServiceModel.Channels;
using System.Reflection;

namespace MBWebService.Service
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    [ServiceKnownType(typeof(MetadataItem))]
    [ServiceKnownType(typeof(BasicCollectionItem))]
    public class MediaBrowserService : IMediaBrowserService, IWebPageService, IDirectImages
    {
        WebServiceHost host;

        #region IMediaBrowserService Members

        public PictureItem GetImage(Guid id, ImageTypes imageType, int maxHeight, int maxWidth)
        {
            return ServiceHelper.Instance.GetImage(id, imageType, maxHeight, maxWidth);
        }

        public MetadataItem GetMetadata(Guid id)
        {
            return ServiceHelper.Instance.GetMetadata(id);
        }

        public string getStreamItems(Guid id)
        {
            return ServiceHelper.Instance.getStreamItems(id);
        }

        public bool StreamItem(Guid id, string fname, string url)
        {
            return ServiceHelper.Instance.StreamItem(id, fname, url);
        }

        public BasicItem GetItem(Guid id)
        {
            return ServiceHelper.Instance.GetItem(id);
        }

        public BasicCollectionItem GetStartUpFolders()
        {
            LogMessage("Attempting to get startup folders");
            return ServiceHelper.Instance.GetStartUpFolders();
        }

        public BasicCollectionItem GetCollection(Guid id)
        {
            return ServiceHelper.Instance.GetCollection(id);
        }

        public TrailerInfo[] GetTrailers(Guid id)
        {
            return ServiceHelper.Instance.GetTrailers(id);
        }

        public PlaybackDevice[] GetAttachedDevices()
        {
            return ServiceHelper.Instance.GetAttachedDevices();
        }

        public BasicCollectionItem GetRecentlyAdded(Guid id)
        {
            return ServiceHelper.Instance.GetRecentlyAdded(id);
        }

        public BasicCollectionItem GetRecentlyWatched(Guid id)
        {
            return ServiceHelper.Instance.GetRecentlyWatched(id);
        }

        #region Client Specific

        public bool PlayItem(Guid id, string player, bool queue)
        {
            return ServiceHelper.Instance.PlayItem(id, player, queue);
        }

        public void SendCommand(CommandTypes command, string player)
        {
            ServiceHelper.Instance.SendCommand(command, player);
        }

        public NowPlayingItem GetNowPlaying(bool waitForUpdate, string player)
        {
            return ServiceHelper.Instance.GetNowPlaying(waitForUpdate, player);
        }

        public void Seek(int seconds, string player)
        {
            ServiceHelper.Instance.Seek(seconds, player);
        }

        public void GoToScreen(ScreenType screenType, string extraInfo, string player)
        {
            ServiceHelper.Instance.GoToScreen(screenType, extraInfo, player);
        }

        public void PlayTrailer(TrailerInfo trailer, string player)
        {
            ServiceHelper.Instance.PlayTrailer(trailer, player);
        }

        #endregion

        #endregion

        #region IWebPageService Members

        public Stream GetWebFile(string filename)
        {
            Stream retVal = null;

            if (filename == "test")
            {
                retVal = Test();
            }
            else if (filename.EndsWith(".html") )
            {
                retVal = GetWebFileInDir(string.Empty, filename);
            }

            return retVal;
        }

        public Stream GetWebFileInDir(string filetype, string filename)
        {
            Stream retVal = null;

            try
            {
                string extension = Path.GetExtension(filename).Replace(".", string.Empty);

                if (!filename.IsNullOrEmpty())
                {
                    if (AppSettings.MimeTypes.ContainsKey(extension))
                    {
                        if (!filetype.IsNullOrEmpty())
                            filetype += "\\"; // add the path separated.
                        
                        FileInfo file = new FileInfo(Path.Combine(AppSettings.WebPageBaseDirectory.FullName, string.Format(@"{0}{1}", filetype, filename)));
                        if (File.Exists(file.FullName))
                        {
                            retVal = new FileStream(file.FullName, FileMode.Open, FileAccess.Read);
                            
                        }
                        else if (extension == "html")
                        {
                            // return a '404' page
                            retVal = GetWebPageAsStream("Invalid file path", 
                                string.Format("ERROR <br /><br />Sorry, could not find the file you requested, ensure the file '{0}' exists", file.FullName));
                        }
                    }

                    WebOperationContext.Current.OutgoingResponse.ContentType = GetContentType(extension);
                }
            }
            catch (Exception ex)
            {
                MBWebService.Core.Logging.Logger.Instance.LogMessage("Error getting web file {0},{1}; ERROR: {2}", filetype, filename, ex.Message);
            }
            return retVal;
        }

        public Stream Test()
        {
            Stream stream = GetWebPageAsStream("Test Page", string.Format("Service is running successfully.<br /> <br />Version: {0}", Assembly.GetExecutingAssembly().GetName().Version));
            WebOperationContext.Current.OutgoingResponse.ContentType = GetContentType("html");
            return stream;
        }

        #endregion

        #region IDirectImages

        public Stream GetDirectImage(Guid id, ImageTypes imageType, int maxHeight, int maxWidth)
        {
            try
            {
                PictureItem item = GetImage(id, imageType, maxHeight, maxWidth);
                WebOperationContext.Current.OutgoingResponse.ContentType = GetContentType(item.FileExtension);
                return item.PictureStream;
            }
            catch (Exception ex)
            {
                LogMessage("Error Retrieving GetDirectImage for id:'{0}'  :'{1}' ERROR:'{2}'", id, imageType, ex.Message);
                return null;
            }
        }

        #endregion

        public void Initialise(Uri uri)
        {
            try
            {
                this.host = new WebServiceHost(this, uri);
                JSONPBindingElement bindingElement = new JSONPBindingElement();
                CustomBinding binding = new CustomBinding(bindingElement, new HttpTransportBindingElement
                {
                    ManualAddressing = true
                });

                var behaviour = new WebHttpBehavior
                {
                    //HelpEnabled = true,
                    //FaultExceptionEnabled = true
                };

                this.host.AddServiceEndpoint(typeof(IMediaBrowserService), binding, string.Empty)
                    .Behaviors.Add(behaviour);
                LogMessage("IMediaBrowserService added successfully...");

                this.host.AddServiceEndpoint(typeof(IWebPageService), new WebHttpBinding(), "web")
                    .Behaviors.Add(new WebHttpBehavior());
                LogMessage("IWebPageService added successfully...");

                this.host.AddServiceEndpoint(typeof(IDirectImages), new WebHttpBinding(), "directimage")
                    .Behaviors.Add(new WebHttpBehavior());
                LogMessage("IDirectImages added successfully...");

                this.host.Open();
                LogMessage("Service opened successfully...");
            }
            catch (Exception ex)
            {
                LogMessage("Error Initialising service; ERROR: {0}", ex.Message);
                throw;
            }
        }

        private Stream GetWebPageAsStream(string title, string content)
        {
            string html = string.Format(@"<html><head><title>{0}</title></head><body>{1}</body></html>", title, content);
            var bytes = Encoding.ASCII.GetBytes(html);
            MemoryStream stream = new MemoryStream(bytes);
            return stream;
        }

        private void LogMessage(string message, params object[] stringFormatArgs)
        {
            MBWebService.Core.Logging.Logger.Instance.LogMessage(message, stringFormatArgs);
        }

        private string GetContentType(string type)
        {
            string retVal = string.Empty;

            if (AppSettings.MimeTypes.ContainsKey(type))
            {
                retVal = AppSettings.MimeTypes[type];
            }

            return retVal;
        }
    }
}
